/**
 * @IdentifierFactory.java  COPYRIGHT xiaojian
 * 
 * Created on 2018年3月16日 下午3:44:37
 */
package xj.toolkit.util;

import java.util.Base64;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Preconditions;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;

/**
 * length(2byte) type(1byte) value(xxbyte) 长度至少超过三个字节。 length = 1 + value.length
 * 
 * @author <a href="mailto:cxj2000@gmail.com">xiaojian.cao</a>
 *
 */
public class IdentifierFactory {

	private static final Logger logger = LoggerFactory.getLogger(IdentifierFactory.class);

	private static BiMap<Byte, Class<?>> typeIdentifier = HashBiMap.create();

	static {
		typeIdentifier.put((byte) 0x0, IntIdentifier.class);
		typeIdentifier.put((byte) 0x1, UUIDIdentifier.class);
	}

	/**
	 * 从字节数组中生成一个标识。字节前面不需要带有长度信息。也就是type + value。
	 * 
	 * @param idByte
	 *            字节数组
	 * @return
	 */
	public static Identifier<?> fromByte(byte[] idByte) throws UnsupportIdTypeException {
		Preconditions.checkArgument(idByte != null & idByte.length > 3);

		//byte[] length = ArrayUtils.subarray(idByte, 0, 2);
		byte idType = idByte[2];
		byte[] content = ArrayUtils.subarray(idByte, 3, idByte.length);

		Class<?> identifierClass = typeIdentifier.get(idType);
		if (identifierClass == null) {
			throw new UnsupportIdTypeException("Unsupport type[" + idType + "].");
		}

		Identifier<?> result = null;
		try {
			result = (Identifier<?>) identifierClass.newInstance();
		} catch (Exception e) {
			logger.debug("IdentifierFactory error.", e);
			return null;
		}

		return result.fromByte(content);
	}

	/**
	 * 通过base64编码过的二进制流来生成一个ID。
	 * 
	 * @param string
	 * @return
	 */
	public static Identifier<?> fromString(String string) {
		Preconditions.checkArgument(StringUtils.isNotBlank(string));

		byte[] bs = Base64.getDecoder().decode(string);

		return fromByte(bs);
	}

	/**
	 * 通过id生成base64编码的字符串。
	 * 
	 * @param id
	 * @return
	 */
	public static String gerIdString(Identifier<?> id) {
		Preconditions.checkArgument(id != null);

		byte[] bs = gerIdByte(id);

		return Base64.getEncoder().encodeToString(bs);
	}

	/**
	 * 从一个Identifier对象生成字节流。带有长度信息，legth+type+value。
	 * 
	 * @param id
	 * @return
	 * @throws UnsupportIdTypeException
	 */
	public static byte[] gerIdByte(Identifier<?> id) throws UnsupportIdTypeException {
		Preconditions.checkArgument(id != null);

		Byte type = typeIdentifier.inverse().get(id.getClass());
		if (type == null) {
			throw new UnsupportIdTypeException("Unsupport type[" + id.getClass() + "].");
		}

		byte[] content = id.valueAsByte();
		int length = 1 + content.length;

		return ByteUtils.union(DefaultNumberCodecs.getBigEndianNumberCodec().int2Bytes(length, 2), new byte[] { type },
				content);
	}

	public static void main(String[] args) {
		// Identifier identifier = new UUIDIdentifier();
		// System.out.println("----->" + identifier);
		// String en = IdentifierFactory.gerIdString(identifier);
		// System.out.println("------------>" + en);
		//
		// System.out.println(IdentifierFactory.fromString(en));

		IntIdentifier id = new IntIdentifier(1761621109);
		System.out.println(ByteUtils.bytesAsHexString(IdentifierFactory.gerIdByte(id), 10));

		byte[] b = new byte[] { 0x0, 0x4, 0x0, 0x0, 0x0, 0x0 };

		System.out.println(IdentifierFactory.fromByte(b));

	}
}